using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;
using static TripleMatch.LevelGenerator;

namespace TripleMatch
{
    public class LevelDataGenerateHandler_Square : LevelDataGenerateHandler { }


    /// <summary>
    /// 关卡数据生成器 返回生成关卡的层级信息
    /// </summary>
    public class LevelDataGenerateHandler
    {
        /// <summary>
        /// 默认的生成器按照生成方块的形式去进行生成
        /// </summary>
        /// <param name="_standardData"></param>
        /// <param name="_extraData"></param>
        /// <param name="_generateData"></param>
        /// <returns></returns>
        public virtual List<LevelObjLayerData> GenerateLevelData(LevelConfigData _standardData, LevelConfigData _extraData, LevelGenerateData _generateData)
        { 
            int totalCount = 0;

            int dataTotalCount = _standardData.totalCount + _extraData.totalCount;
            int dataTotalLayer = _standardData.totalLayer + _extraData.totalLayer;

            List<LevelObjLayerData> resultList = new List<LevelObjLayerData>();
            Vector2Int averageLayerSize = GetCloseDivisors(dataTotalCount / dataTotalLayer);

            Debug.LogFormat("根据数据生成基础版本：总块数{0} 总层数{1}", dataTotalCount, dataTotalLayer);
            switch (_generateData.gradientType)
            {
                case GradientType.Decrease:
                case GradientType.Fusiform:
                case GradientType.SameSize:
                case GradientType.Increase:
                default:
                    for (int i = dataTotalLayer / 2; i > dataTotalLayer / 2 - dataTotalLayer; i--)
                    { 
                        LevelObjLayerData layerData = new LevelObjLayerData();
                        layerData.layerSize = new Vector2Int(averageLayerSize.y + i, averageLayerSize.x + i);
                        layerData.count = layerData.layerSize.x * layerData.layerSize.y;
                        layerData.shapeType = _generateData.shapeType;
                        resultList.Add(layerData);
                        Debug.LogFormat("生成当前层 {0} layerSize:{1}", i - _standardData.totalLayer / 2, layerData.layerSize.ToString());

                        totalCount += layerData.count;
                    }
                    break;
            }

            //额外数据生成层
            int leftCount = dataTotalCount - totalCount;
            leftCount = leftCount < 0 ? 0 : leftCount;
            leftCount = leftCount + (3 - (totalCount + leftCount) % 3);
            if (leftCount > 0)
            {
                LevelObjLayerData extraLayer = new LevelObjLayerData();
                extraLayer.layerSize = new Vector2Int(leftCount, 1);
                extraLayer.count = leftCount;
                extraLayer.shapeType = _generateData.shapeType;
                resultList.Add(extraLayer);
                totalCount += leftCount;
                Debug.LogFormat("额外层信息 leftCount:{0}", leftCount);
            }

            //计算Sprite种类 
            //随机规则：每个装饰物会有权重的分配
            //根据品质分配（1-5，2-2，3-3），根据品类分配（1-2，2-6，3-2），根据是否是已获得物品（1-50，2-5）

            int randomBase = 0;
            List<int> randomRange = new List<int>();
            randomRange.Add(0);
            DecorationInfoData[] decorationInfoDatas = DecorationsManager.S.GetDecorationInfoDatas();
            for (int i = 0; i < decorationInfoDatas.Length; i++)
            {
                DecorationData decorationData = DecorationsManager.S.GetDecorationData(decorationInfoDatas[i].id);
                if (decorationData != null && decorationInfoDatas[i].decorationType == 0) break;
                else
                {
                    int tempValue = qualityValueArray[decorationInfoDatas[i].qualityIndex];
                    tempValue += typeValueArray[decorationInfoDatas[i].decorationType];

                    if (decorationData == null) tempValue += 2;
                    else tempValue += 8;

                    randomBase += tempValue;
                    randomRange.Add(randomBase);
                }
            }

            List<int> randomResultList = new List<int>();

            if (DataManager.S.level < 1) randomResultList.Add(0);

            Dictionary<int, int> tempDic = new Dictionary<int, int>();
            int randomTime = totalCount / 3;
            int randomMax = randomTime / randomRange.Count;

            while (randomResultList.Count < randomTime)
            {
                int randomValue = UnityEngine.Random.Range(0, randomBase);

                for (int i = 0; i < randomRange.Count - 1; i++)
                {
                    if (randomValue >= randomRange[i] && randomValue < randomRange[i + 1])
                    {
                        if (!tempDic.ContainsKey(i))
                        {
                            tempDic.Add(i, 1);
                            randomResultList.Add(i);
                        }
                        else if (tempDic[i] <= randomMax)
                        {
                            tempDic[i]++;
                            randomResultList.Add(i);
                        }
                        else { }
                        break;
                    }
                }
            }
            Debug.LogFormat("randomResultList Count:{0}", randomResultList.Count);

            List<int> tempList = randomResultList.ToList();
            randomResultList.AddRange(tempList);
            randomResultList.AddRange(tempList);

            Debug.LogFormat("randomResultList Count:{0}", randomResultList.Count);

            //给Layer分配Sprite以及位置数据
            int spriteIndex = 0;
            for (int i = 0; i < resultList.Count; i++)
            {
                resultList[i].RandomLayerData(randomResultList.Skip(spriteIndex).Take(resultList[i].layerSize.x * resultList[i].layerSize.y).ToList());
                spriteIndex += resultList[i].layerSize.x * resultList[i].layerSize.y;
            }

            return resultList;
        }

        private int[] qualityValueArray = new int[4] { 0, 5, 2, 3 };
        private int[] typeValueArray = new int[4] { 0, 2, 6, 2 };

        protected Vector2Int GetCloseDivisors(int _total)
        {
            int closeFactor = -1;
            int closeDivisor = 0;
            for (int i = 1; i < _total + 1; i++)
            { 
                if (_total % i == 0)
                {
                    if (closeFactor == -1 || Mathf.Abs(i - _total / i) < closeFactor)
                    {
                        closeFactor = Mathf.Abs(i - _total / i);
                        closeDivisor = i;
                    } 
                }
            }
            return new Vector2Int(closeDivisor, _total / closeDivisor);
        }
    }

    public struct LevelObjData
    {
        public int spriteType;
        public Vector2 objPostion;
        public LevelObj levelObj;
    }
}

